import os
import openpyxl
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment
from openpyxl.comments import Comment

from src import date


class Duty:
    def __init__(self, value="", comm="", lock=False):
        self.value = value
        self.comm = comm
        self.lock = lock

    @staticmethod
    def persist():
        return ["正", "门", "正门", "业余", "值", "值休", "休"]


class Schdule:
    def __init__(self, year=None, month=None):
        if year is None or month is None:
            year, month = date.get_next_month()
        self.filename = f"{year}年{month}月.xlsx"
        self.year = year
        self.month = month
        self.days = date.get_days(year, month)
        self.weekdays = date.get_weekdays(year, month)
        self.holidays = set()
        self.data = {}
        self.load()

    def init_holidays(self):
        self.holidays.clear()
        for day in self.days:
            weekday = date.get_weekday(self.year, self.month, day)
            if weekday == "六" or weekday == "日":
                self.holidays.add(day)

    def stat_day(self, day, duty, doctors):
        count = 0
        stats = {}
        for name in self.data:
            dutys = self.data[name]
            if dutys[day - 1].value == duty:
                count += 1
                if name not in doctors:
                    continue
                doctor = doctors[name]
                for k in doctor:
                    v = doctor[k]
                    if v in stats:
                        stats[v] += 1
                    else:
                        stats[v] = 1
        return count, stats

    def stat_doctor(self, doctor):
        stats = {}
        start = -100
        min_gap = 100
        dutys = self.data[doctor]
        for i, duty in enumerate(dutys):
            if duty.value == "值休":
                start = i
            elif duty.value == "值":
                min_gap = min(min_gap, i - start - 1)
            if duty.value in stats:
                stats[duty.value] += 1
            else:
                stats[duty.value] = 1
        if "值" in stats and min_gap < len(self.days):
            stats["值"] = f"{stats['值']}({min_gap})"
        return stats

    def change(self, year, month):
        self.filename = f"{year}年{month}月.xlsx"
        self.year = year
        self.month = month
        self.days = date.get_days(year, month)
        self.weekdays = date.get_weekdays(year, month)
        self.load()

    def clean(self):
        for name in self.data:
            dutys = self.data[name]
            for day in self.days:
                duty = dutys[day - 1]
                if duty.lock:
                    continue
                duty.value = ""
                duty.comm = ""

    def move(self, name, to):
        if name == to:
            return False
        doctor = self.data.pop(name)
        tmp_data = self.data.copy()
        self.data.clear()
        for key, val in tmp_data.items():
            self.data[key] = val
            if key == to:
                self.data[name] = doctor
        return True

    def load(self, filename=None):
        if filename is None:
            filename = self.filename
        if os.path.exists(filename):
            wb = openpyxl.load_workbook(filename)
            ws = wb.active
            self.holidays.clear()
            self.data.clear()
            for day in self.days:
                color = ws.cell(row=1, column=day + 1).font.color
                if color is None:
                    continue
                rgb = color.rgb
                if type(rgb) is not str:
                    continue
                r = int(rgb[2:4], 16)
                if r > 100:
                    self.holidays.add(day)
            for row in range(3, ws.max_row + 1):
                name = ws.cell(row=row, column=1).value
                if name is None:
                    continue
                name = name.strip()
                if name == "":
                    continue
                dutys = []
                for day in self.days:
                    cell = ws.cell(row=row, column=day + 1)
                    value = "" if cell.value is None else cell.value.strip()
                    comm = "" if cell.comment is None else cell.comment.text
                    dutys.append(Duty(value, comm, cell.font.bold))
                self.data[name] = dutys
        else:
            self.init_holidays()
            self.data.clear()

    def save(self, filename=None):
        if filename is None:
            filename = self.filename
        wb = Workbook()
        ws = wb.active
        for day, weekday in zip(self.days, self.weekdays):
            ws.cell(row=1, column=day + 1, value=day)
            ws.cell(row=2, column=day + 1, value=weekday)
        row = 3
        for name in self.data:
            ws.cell(row=row, column=1, value=name.strip())
            dutys = self.data[name]
            for day in self.days:
                duty = dutys[day - 1]
                cell = ws.cell(row=row, column=day + 1, value=duty.value)
                if duty.comm:
                    cell.comment = Comment(duty.comm, "")
                if duty.lock:
                    cell.font = Font(name="微软雅黑", bold=duty.lock)
            row += 1
        # 设置节假日颜色
        for i, row in enumerate(ws.iter_rows()):
            for j, cell in enumerate(row):
                if j in self.holidays:
                    cell.font = Font(
                        name=cell.font.name, bold=cell.font.bold, color="ff0000"
                    )
                cell.alignment = Alignment(horizontal="center", vertical="center")
        wb.save(filename)
